package cz.semjobKB.gui;


import com.vaadin.ui.*;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import cz.semjobKB.controller.Controller;
import cz.semjobKB.knowledge.api.IExtractedKnowledge;
import cz.semjobKB.knowledge.api.ITerminologyItem;
import cz.semjobKB.knowledge.api.ITripleItem;
import cz.semjobKB.knowledge.impl.ExtractedKnowledge;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map.Entry;


/**
 * Used to display founded terminologies and triples and let user decide what is important and will be added
 * into the knowledge graph and stored in the database
 */
@SuppressWarnings("restriction")
@Component
public class SelectKnowledgeLayout extends VerticalSplitPanel {
			
	/**
	 * 
	 */
	private static final long serialVersionUID = -5282503207312068539L;
	
	@Autowired
    private ApplicationContext applicationContext;
	
	private Button storeKnowledge = new Button("Store");
	private final String SUBJECT = "Subject";
	private final String PREDICATE = "Predicate";
	private final String OBJECT = "Object";
	private final String TERMINOLOGY = "Terminology";
	private final String FREQUENCY = "Frequency";		
	private final String EXIST = "Exists in DB";
	private final String ADD = "Add";
	
	private IExtractedKnowledge knowledge;
	private File document;	
	
	
	@PostConstruct
    protected void init() {
		
	}

    /**
     * Displays triples and terminologies founded. Allows user to select/deselect what will be stored in the DB.
     * Triples and terminologies are passed in a linked hash map with a boolean value. This boolean values marks if
     * that the terminology or triple already exists in the database.
     * @param triples           Map of triples
     * @param terminology       Map of terminologies
     * @param originalKnowledge Original Extracted Knowledge class
     * @param docToProcess      Processed document
     * @param controller        Controller class
     * @return                  Container
     */
	@SuppressWarnings("unchecked")
	protected ComponentContainer suggestExtractedKnowledge(LinkedHashMap<ITripleItem, Boolean> triples, 
			LinkedHashMap<ITerminologyItem, Boolean> terminology, 
			IExtractedKnowledge originalKnowledge,
			File docToProcess, final Controller controller) {
				
		knowledge = originalKnowledge;
		document = docToProcess;
		
		this.setSplitPosition(95);
		this.setLocked(true);
		HorizontalSplitPanel tableSplitPanel = new HorizontalSplitPanel();
		tableSplitPanel.setSplitPosition(60);
		tableSplitPanel.setLocked(true);
		
		final Table tripleList = new Table();
		final Table terminologyList = new Table();
		
		tripleList.setSortEnabled(false);
		tripleList.addContainerProperty(SUBJECT, String.class,  null);
		tripleList.addContainerProperty(PREDICATE, String.class,  null);
		tripleList.addContainerProperty(OBJECT, String.class, null);
		tripleList.addContainerProperty(EXIST, String.class, null);
		tripleList.addContainerProperty(ADD, CheckBox.class, null);
		
		int index = 0;
		for ( Entry<ITripleItem, Boolean> entry : triples.entrySet()) {
			Integer rowId = new Integer(index); 
			tripleList.addItem(rowId);
			tripleList.getContainerProperty(rowId, SUBJECT).setValue(entry.getKey().getSubjectWord());
			tripleList.getContainerProperty(rowId, PREDICATE).setValue(entry.getKey().getPredicateWord());
			tripleList.getContainerProperty(rowId, OBJECT).setValue(entry.getKey().getObjectWord());			
			if (entry.getValue()) {								
				tripleList.getContainerProperty(rowId, EXIST).setValue("Yes");				
			} else {
				tripleList.getContainerProperty(rowId, EXIST).setValue("No");
			}
			CheckBox checkBox = new CheckBox();
			checkBox.setValue(false);
			tripleList.getContainerProperty(rowId, ADD).setValue(checkBox);
			index++;
		}
		
		terminologyList.setSortEnabled(false);
		terminologyList.addContainerProperty(TERMINOLOGY, String.class,  null);
		terminologyList.addContainerProperty(FREQUENCY, Integer.class,  null);		
		terminologyList.addContainerProperty(EXIST, String.class, null);
		terminologyList.addContainerProperty(ADD, CheckBox.class, null);
		index = 0;
		for ( Entry<ITerminologyItem, Boolean> entry : terminology.entrySet()) {
			Integer rowId = new Integer(index); 
			terminologyList.addItem(rowId);			
			terminologyList.getContainerProperty(rowId, TERMINOLOGY).setValue(entry.getKey().getLemma());
			terminologyList.getContainerProperty(rowId, FREQUENCY).setValue(entry.getKey().getFrequency());						
			if (entry.getValue()) {				
				terminologyList.getContainerProperty(rowId, EXIST).setValue("Yes");				
			} else {				
				terminologyList.getContainerProperty(rowId, EXIST).setValue("No");
			}
			CheckBox checkBox = new CheckBox();
			checkBox.setValue(true);
			terminologyList.getContainerProperty(rowId, ADD).setValue(checkBox);
			index++;
		}
		
		tripleList.setSizeFull();
		terminologyList.setSizeFull();
		tableSplitPanel.addComponent(tripleList);
		tableSplitPanel.addComponent(terminologyList);

        //Find marked triples and terminologies and create new ExtractedKnowledge class
		storeKnowledge.addClickListener(new ClickListener() {
			
			/**
			 * 
			 */
			private static final long serialVersionUID = 8978460903852887743L;

			public void buttonClick(ClickEvent event) {
				List<ITripleItem> triplesToStore = new ArrayList<ITripleItem>();
				Collection<?> iterTriple = tripleList.getContainerDataSource().getItemIds();
				for(int i = 0 ; i < iterTriple.size(); i++) {
					CheckBox test = (CheckBox)tripleList.getContainerProperty(i, ADD).getValue();
					if (test.getValue()) {
						triplesToStore.add(knowledge.getTriples().get(i));
					}
				}
				
				List<ITerminologyItem> terminologyToStore = new ArrayList<ITerminologyItem>();
				Collection<?> iterTerm = terminologyList.getContainerDataSource().getItemIds();
				for(int i = 0 ; i < iterTerm.size(); i++) {
					CheckBox test = (CheckBox)terminologyList.getContainerProperty(i, ADD).getValue();
					if (test.getValue()) {
						terminologyToStore.add(knowledge.getTerminology().get(i));
					}
				}
				IExtractedKnowledge finalKnowledge = new ExtractedKnowledge(triplesToStore, 
						terminologyToStore, knowledge.getSentencesCount(), 
						knowledge.getSentFull(), knowledge.getWordCount());
				controller.storeFinalDocument(finalKnowledge, document);
				
			}
		
		});
		storeKnowledge.setSizeFull();		
		this.addComponent(tableSplitPanel);
		this.addComponent(storeKnowledge);
		this.setSizeFull();
		return this;
	}

}
